package com.github.wxiaoqi.security.auth.controller;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.github.wxiaoqi.security.auth.common.config.UserAuthConfig;
import com.github.wxiaoqi.security.auth.feign.CrmCoreFeign;
import com.github.wxiaoqi.security.auth.service.AuthService;
import com.github.wxiaoqi.security.auth.service.Kaptcha;
import com.github.wxiaoqi.security.auth.util.RSAUtils;
import com.github.wxiaoqi.security.auth.util.user.JwtAuthenticationRequest;
import com.github.wxiaoqi.security.common.entity.PlatformSafetyConfigCommon;
import com.github.wxiaoqi.security.common.msg.ObjectRestResponse;
import com.github.wxiaoqi.security.common.msg.ResponseCode;
import com.github.wxiaoqi.security.common.util.Base64Utils;
import com.github.wxiaoqi.security.common.util.EntityUtils;

import lombok.extern.slf4j.Slf4j;

@RestController
@RequestMapping("jwt")
@Slf4j
public class AuthController {
	
	@Autowired
    protected HttpServletRequest request;
	@Autowired
	private UserAuthConfig userAuthConfig;
    @Value("${jwt.token-header}")
    private String tokenHeader;
    @Autowired
    private AuthService authService;
    @Autowired
    private Kaptcha kaptcha;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @Autowired
    private CrmCoreFeign crmCoreFeign;
    
    /**
     * pc运营后台、商户、平台管理员登录授权接口
     * @param authenticationRequest
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "token", method = RequestMethod.POST)
    public Map<String, Object> createAuthenticationToken(
            @RequestBody JwtAuthenticationRequest authenticationRequest) throws Exception {
    	Map<String, Object> respMap = new HashMap<>();
        log.info(authenticationRequest.getUsername()+" require logging...");
        respMap = authService.login(authenticationRequest);
        return respMap;
    }
    
    /**
     * app端、小程序运营后台登录授权接口
     * @param authenticationRequest
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "operator/token", method = RequestMethod.POST)
    public Map<String, Object> operatorAuthenticationToken(
            @RequestBody JwtAuthenticationRequest authenticationRequest) throws Exception {
    	Map<String, Object> respMap = new HashMap<>();
        log.info(authenticationRequest.getUsername()+" require logging...");
        respMap = authService.operatorLogin(authenticationRequest);
        return respMap;
    }

    /**
     * 所接入平台请求获取授权各自token接口,针对系统后台授权
     * @author centerroot
     * @time 创建时间:2018年9月21日上午11:10:52
     * @param authenticationRequest
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "platformToken", method = RequestMethod.POST)
    public Map<String, Object> createPlatformAuthToken(
            @RequestBody JwtAuthenticationRequest authenticationRequest) throws Exception {
    	Map<String, Object> respMap = new HashMap<String, Object>();
    	String token = null;
        log.info("平台请求获取token请求参数：{}",EntityUtils.beanToMap(authenticationRequest));
    	if("".equals(authenticationRequest.getAppId())||null==authenticationRequest.getAppId()){
    		respMap.put("code", ResponseCode.TOKEN_APPIDISNULL_CODE.getCode());
    		respMap.put("msg", ResponseCode.TOKEN_APPIDISNULL_CODE.getMessage());
            log.info("平台请求获取token响应参数：{}",respMap);
    		return respMap;
    	}
    	if("".equals(authenticationRequest.getKey())||null==authenticationRequest.getKey()){
    		respMap.put("code", ResponseCode.TOKEN_KEYISNULL_CODE.getCode());
    		respMap.put("msg", ResponseCode.TOKEN_KEYISNULL_CODE.getMessage());
            log.info("平台请求获取token响应参数：{}",respMap);
    		return respMap;
    	}
    	
    	Map<String, Object> platformSafetyReqMap = new HashMap<String, Object>();
    	platformSafetyReqMap.put("appid", authenticationRequest.getAppId());
    	Map<String, Object> platformSafetyRespMap = crmCoreFeign.queryPlatformInfo(platformSafetyReqMap);
    	if (null == platformSafetyRespMap || !ResponseCode.OK.getCode().equals(platformSafetyRespMap.get("code"))) {
    		respMap = platformSafetyRespMap;
            log.info("平台请求获取token响应参数：{}",respMap);
    		return respMap;
		}
    	PlatformSafetyConfigCommon platformSafetyConfig = (PlatformSafetyConfigCommon) platformSafetyRespMap.get("platformSafetyConfig");
    	/**
    	 * 用应用对应的私钥解密获取签名用的盐值
    	 * */
    	byte[]source=Base64Utils.decode(authenticationRequest.getKey());
    	byte[]decryptSaltValue=null;
    	try {
    		decryptSaltValue =RSAUtils.decryptByPrivateKey(source,platformSafetyConfig.getPrivateKey());
		} catch (Exception e1) {
			log.info("授权解析传输数据报错:"+e1.getMessage());
			e1.printStackTrace();
    		respMap.put("code", ResponseCode.TOKEN_AUTHRESOLVEPARAMS_CODE.getCode());
    		respMap.put("msg", ResponseCode.TOKEN_AUTHRESOLVEPARAMS_CODE.getMessage());
            log.info("平台请求获取token响应参数：{}",respMap);
    		return respMap;
		}
    	String saltValue =new String(decryptSaltValue);
    	if (null == saltValue || !saltValue.equals(platformSafetyConfig.getAppKey())) {
    		log.info("授权解析盐值错误，解析盐值：{}，正确盐值：{}", saltValue, platformSafetyConfig.getAppKey());
    		respMap.put("code", ResponseCode.TOKEN_SALTKEY_ERROR_CODE.getCode());
    		respMap.put("msg", ResponseCode.TOKEN_SALTKEY_ERROR_CODE.getMessage());
            log.info("平台请求获取token响应参数：{}",respMap);
    		return respMap;
		}
    	
    	/**
    	 * 获取token
    	 * */
		try {
			token = authService.createCrmapiToken(platformSafetyConfig);
		} catch (Exception e) {
			log.info("授权获取TOKEN数据报错:"+e.getMessage());
			e.printStackTrace();
			respMap.put("code", ResponseCode.TOKEN_ISNULL_CODE.getCode());
    		respMap.put("msg", ResponseCode.TOKEN_ISNULL_CODE.getMessage());
            log.info("平台请求获取token响应参数：{}",respMap);
    		return respMap;
		}
        if("".equals(token)||null==token){
			respMap.put("code", ResponseCode.TOKEN_ISNULL_CODE.getCode());
    		respMap.put("msg", ResponseCode.TOKEN_ISNULL_CODE.getMessage());
            log.info("平台请求获取token响应参数：{}",respMap);
    		return respMap;
        }
        //缓存token
    	redisTemplate.opsForValue().set(platformSafetyConfig.getAppId(), token, 7200, TimeUnit.MINUTES);
    	
    	respMap.put("code", ResponseCode.OK.getCode());
		respMap.put("msg", ResponseCode.OK.getMessage());
		respMap.put("token", token);
        log.info("平台请求获取token响应参数：{}",respMap);
		return respMap;
    }
    
    @RequestMapping(value = "refresh", method = RequestMethod.GET)
    public ObjectRestResponse<String> refreshAndGetAuthenticationToken(
            HttpServletRequest request) throws Exception {
        String token = request.getHeader(tokenHeader);
        String refreshedToken = authService.refresh(token);
        return new ObjectRestResponse<>().data(refreshedToken);
    }

    @RequestMapping(value = "verify", method = RequestMethod.GET)
    public ObjectRestResponse<?> verify() throws Exception {
        authService.validate(request.getHeader(userAuthConfig.getTokenHeader()));
        return new ObjectRestResponse<>();
    }
    
    /***
     * 根据配置后台配置的platformId 生产token
     * 加密规则:用的sha256;key用的是RSA公私秘钥加密的
     * *//*
    @RequestMapping(value = "crmToken", method = RequestMethod.POST)
    public JwtAuthenticationResponse createAuthenticationTokenForCrm(@RequestBody JwtAuthenticationRequest authenticationRequest) throws Exception {
    	String token="";
    	JwtAuthenticationResponse response= new JwtAuthenticationResponse();
    	if(StringUtils.isEmpty(authenticationRequest.getPlatformId())||StringUtils.isEmpty(authenticationRequest.getSaltKey())){
    		log.info("获取授权crmtoken报错：平台编号或盐值不能为空");
    		response.setCode(ResponseCode.INVALID_FIELDS.getCode());
    		response.setMsg((ResponseCode.INVALID_FIELDS.getMessage()));
    		response.setSuccess(false);
    		return response;
    	}
    	*//**
    	 * 根据platformId获取platformId 对应的公私秘钥，然后用解密获取用户saltkey（签名加密用的盐值）
    	 * *//*
    	ValidateAppInfoRsp appInfoRsp=null;
		try {
			appInfoRsp = authService.getValidateAppInfo(authenticationRequest.getAppId());
			if(null==appInfoRsp||!"200".equals(appInfoRsp.getCode())){
				return ResponseEntity.ok(new JwtAuthenticationResponse(StatesConstants.TOKEN_AUTHCHECKAPPID_CODE.getCode(),StatesConstants.TOKEN_AUTHCHECKAPPID_CODE.getMsg(),""));
			}
		} catch (Exception e2) {
			e2.printStackTrace();
			logger.info("授权验证APPid数据报错:"+e2.getMessage());
			return ResponseEntity.ok(new JwtAuthenticationResponse(StatesConstants.TOKEN_AUTHCHECKAPPID_CODE.getCode(),StatesConstants.TOKEN_AUTHCHECKAPPID_CODE.getMsg(),""));
		}
    	*//**
    	 * 用应用对应的私钥解密获取签名用的盐值
    	 * *//*
    	byte[]source=Base64Utils.decode(authenticationRequest.getKey());
    	byte[]decryptSaltValue=null;
    	try {
    		decryptSaltValue =RSAUtils.decryptByPrivateKey(source,appInfoRsp.getPrivateKey());
		} catch (Exception e1) {
			logger.info("授权解析传输数据报错:"+e1.getMessage());
			e1.printStackTrace();
			return ResponseEntity.ok(new JwtAuthenticationResponse(StatesConstants.TOKEN_AUTHRESOLVEPARAMS_CODE.getCode(),StatesConstants.TOKEN_AUTHRESOLVEPARAMS_CODE.getMsg(),""));
		}
    	*//**
    	 * 获取token
    	 * *//*
    	token = authService.createCrmToken(authenticationRequest.getPlatformId(),authenticationRequest.getSaltKey());
    	response.setSuccess(true);
    	response.setToken(token);
        //缓存token
		redisTemplate.opsForValue().set("auth:token_"+authenticationRequest.getPlatformId(),token);
        return response;
        
    }*/
    /**
     * 获取图形验证码
     * */
    @GetMapping("/imageCode")
    public void render(@RequestParam("date") String date) {
      kaptcha.render();
    }
}